home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / minix / update~4.z / update~4 / lib_stdio_fread.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-06  |  4.3 KB  |  160 lines

  1. /*                f r e a d
  2.  *
  3.  * Read a series of records from an input stream. The function
  4.  * returns the number of items (not bytes) read. The function
  5.  * stops reading when the number of items is satisfied or when
  6.  * EOF is encountered.
  7.  *
  8.  * Patchlevel 1.1
  9.  *
  10.  * Edit History:
  11.  * 05-Sep-1989    Include limits.h if INT_MAX undefined so removing
  12.  *        need to define MINIX when compiling. Fix void *
  13.  *        problems by assigning to an unsigned char *.
  14.  *        Add EINTR repeat code after read().
  15.  * 04-Sep-1989    Add code for reading very large objects.
  16.  * 01-Sep-1989    Use Henry Spencer's ideas to speed up code by reading
  17.  *        directly into buffer.
  18.  */
  19.  
  20. #include "stdiolib.h"
  21.  
  22. #if    defined(BSD)
  23. # include <values.h>
  24. # define INT_MAX    (MAXINT)
  25. #endif
  26.  
  27. #if    !defined(INT_MAX)
  28. # include <limits.h>
  29. #endif
  30.  
  31. /*LINTLIBRARY*/
  32.  
  33. int fread(ptr, size, nitems, fp)
  34.  
  35. void *ptr;                /* buffer */
  36. unsigned size;                /* size of record */
  37. unsigned nitems;            /* number of items */
  38. FILE *fp;                /* stream */
  39.  
  40. {
  41.   int red;                /* bytes read in read call */
  42.   int read();                /* read call */
  43.   unsigned char *p;            /* buffer pointer */
  44.  
  45. /* Phase 1 --- Amount to read overflows INT_MAX */
  46.   unsigned int burstsize;        /* size aligned chunk to read */
  47.   unsigned int itemsperburst;        /* items read per burst */
  48.   unsigned int itemsleft;        /* items left */
  49.   unsigned int copyitems;        /* items to copy */
  50.  
  51. /* Phase 2 --- Write remainder */
  52.   unsigned int bytestotal;        /* total number of bytes */
  53.   unsigned int bytesleft;        /* total number of bytes left */
  54.   unsigned int copybytes;        /* bytes to copy directly to buffer */
  55.   unsigned char *q;            /* pointer into getc buffer */
  56.  
  57. /* Items left to read */
  58.   if ((itemsleft = nitems) == 0 || size == 0)
  59.     return 0;
  60.  
  61. /* Flush stdout */
  62.   if (fp == stdin && TESTFLAG(stdout, _IOLBF))
  63.     (void) fflush(stdout);
  64.  
  65. /* Fix void * casting problems */
  66.   p = (unsigned char *) ptr;
  67.  
  68. /* Read very large objects */
  69.   if ((itemsperburst = INT_MAX / size) == 0) {
  70.     do {
  71.       bytesleft = size;
  72.       do {
  73.     if ((burstsize = BYTESINREADBUFFER(fp)) != 0) {
  74.       if (burstsize > bytesleft)
  75.         burstsize = bytesleft;
  76.       q = GETREADPTR(fp);
  77.       UNROLL_DO(freadlarge, burstsize, *p++ = *q++);
  78.       SETREADPTR(fp, q);
  79.     }
  80.     else {
  81.       if ((burstsize = INT_MAX) > bytesleft)
  82.         burstsize = bytesleft;
  83.       do
  84.         red = read(fileno(fp), (char *) p, (int) burstsize);
  85.       while (red == -1 && errno == EINTR);
  86.       if (red != burstsize)
  87.         return (nitems-itemsleft);
  88.       p += burstsize;
  89.     }
  90.       } while ((bytesleft -= burstsize) != 0);
  91.     } while (--itemsleft);
  92.     return nitems;
  93.   }
  94.  
  95. /* Read large amounts of data first */
  96.   for (burstsize = itemsperburst * size; itemsleft > itemsperburst; ) {
  97.     if (itemsleft == nitems &&
  98.         (copybytes = BYTESINREADBUFFER(fp)) != 0) {
  99.       copyitems = copybytes/size;
  100.       if (copyitems > itemsleft)
  101.     copybytes = (copyitems = itemsleft) * size;
  102.       itemsleft -= copyitems;
  103.       if ((bytesleft = copybytes%size) != 0)
  104.     bytesleft = size-bytesleft;
  105.       q = GETREADPTR(fp);
  106.       UNROLL_DO(freadburst, copybytes, *p++ = *q++);
  107.       SETREADPTR(fp, q);
  108.       if (bytesleft != 0) {
  109.     do
  110.       red = read(fileno(fp), (char *) p, (int) bytesleft);
  111.     while (red == -1 && errno == EINTR);
  112.     if (red != bytesleft)
  113.       return (nitems-itemsleft);
  114.     itemsleft--;
  115.       }
  116.     }
  117.     else {
  118.       do
  119.     red = read(fileno(fp), (char *) p, (int) burstsize);
  120.       while (red == -1 && errno == EINTR);
  121.       if (red != burstsize) {
  122.     if (red == -1)
  123.       red = 0;
  124.     return (nitems-itemsleft) + (red/size);
  125.       }
  126.       p += burstsize;
  127.       itemsleft -= itemsperburst;
  128.     }
  129.   }
  130.  
  131. /* At this point itemsleft contains the number of items left to
  132.  * read. The read buffer may not be empty. itemsleft*size
  133.  * will not overflow INT_MAX.
  134.  */
  135.  
  136.   if ((bytesleft = bytestotal = size*itemsleft) != 0) {
  137.  
  138. /* Partially filled read buffer */
  139.     if ((copybytes = BYTESINREADBUFFER(fp))  != 0) {
  140.       if (copybytes > bytesleft)
  141.     copybytes = bytesleft;
  142.       bytesleft -= copybytes;
  143.       q = GETREADPTR(fp);
  144.       UNROLL_DO(freadbytes, copybytes, *p++ = *q++);
  145.       SETREADPTR(fp, q);
  146.     }
  147.  
  148. /* Read rest of object directly to user buffer */
  149.     if (bytesleft != 0) {
  150.       do
  151.     red = read(fileno(fp), (char *) p, (int) bytesleft);
  152.       while (red == -1 && errno == EINTR);
  153.       if (red != -1)
  154.     bytesleft -= red;
  155.     }
  156.   }
  157.  
  158.   return (nitems-itemsleft) + (bytestotal-bytesleft)/size;
  159. }
  160.